﻿using Microsoft.Xna.Framework;
using SibLib.Render;

namespace SibLib.Entities
{
    /// <summary>
    /// 3D version of the GameplayObject.
    /// </summary>
    /// <remarks>Sadly obtained through copy/paste.</remarks>
    public abstract class GameplayObject3D
    {
        #region Location
        protected Vector3 m_Position;
        /// <summary>
        /// Current position in 3D world.
        /// </summary>
        /// <remarks>
        /// Be careful when using setter, WorldMatrix isn't updated automatically.
        /// </remarks>
        public Vector3 Position
        {
            get { return m_Position; }
            set { m_Position = value; }
        }

        protected Matrix m_WorldMatrix;
        /// <summary>
        /// Current world matrix.
        /// </summary>
        /// <remarks>
        /// Be careful when using setter, Position isn't updated automatically.
        /// </remarks>
        public Matrix WorldMatrix
        {
            get { return m_WorldMatrix; }
            set { m_WorldMatrix = value; }
        }
        #endregion       

        /// <summary>
        /// Radius of object.
        /// </summary>
        /// <remarks>Should be of the containing sphere (ie bounding sphere), not contained sphere.</remarks>
        public float Radius
        {
            get;
            protected set;
        }

        protected BoundingBox m_BoundingBox;
        public BoundingBox BoundingBox
        {
            get { return m_BoundingBox; }
        }

        protected bool m_IsInitialized;

        #region Construction

        protected GameplayObject3D()
        {
            m_IsInitialized = false;
            m_Position = Vector3.Zero;
            m_WorldMatrix = Matrix.Identity;
            Radius = 0.5f;
            m_BoundingBox = new BoundingBox(new Vector3(-0.5f), new Vector3(0.5f));
        }

        #endregion

        #region Setup

        /// <summary>
        /// Default implementation checks m_IsInitialized, calls LoadContent, sets m_IsInitialized.
        /// </summary>
        public virtual void Initialize()
        {
            if (m_IsInitialized)
                return;

            LoadContent();

            m_IsInitialized = true;
        }

        /// <summary>
        /// Empty implementation provided.
        /// </summary>
        protected virtual void LoadContent()
        {

        }

        #endregion

        #region Helpers

        public void Move(Vector3 delta)
        {
            Vector3.Add(ref m_Position, ref delta, out m_Position);
            m_WorldMatrix *= Matrix.CreateTranslation(delta);
        }

        public void Move(float deltaX, float deltaY, float deltaZ)
        {
            m_Position.X += deltaX;
            m_Position.Y += deltaY;
            m_Position.Z += deltaZ;
            m_WorldMatrix *= Matrix.CreateTranslation(deltaX, 0.0f, deltaZ);
        }

        #endregion
    }
}
